#include "CommonOperation.h"
#include "StatusCode.h"
#include "Debug.h"
#include <unistd.h>


CommonOperation::CommonOperation()
{

}

CommonOperation::~CommonOperation()
{
	for (unsigned int i = 0;i <  this->_attributeMethodList.size();i++){
		this->remove(this->_attributeMethodList[i]->attributeID);
	}
}

void CommonOperation::addMethodToList(string attributeID,int optID,Method method)
{
	
	vector <OptMethod *> *optMethodList = this->getMethodList(attributeID);
	// The list is NULL,
	if (optMethodList == NULL){
		AttributeMethod *attributeMethod = new AttributeMethod;
		OptMethod *optMethod = new OptMethod;
		optMethod->optID = optID;
		optMethod->method = method;
		attributeMethod->attributeID = attributeID;
		attributeMethod->methodList.push_back(optMethod);
		this->_attributeMethodList.push_back(attributeMethod);
	}
	// 
	else{
		vector <OptMethod *>::iterator it = this->find(optMethodList,optID);
		// if the method exist,replace it.
		if (it != (*optMethodList).end()){
			(*it)->method = method;
		} // else add a new method.
		else{
			OptMethod *optMethod = new OptMethod;
			optMethod->optID = optID;
			optMethod->method = method;
			(*optMethodList).push_back(optMethod);
		}
	}

}

int CommonOperation::execute(Message &message)
{
	string attributeID;
	int optID = message.getType();
	message.get(Message::HMC_ATTRIBUTE_NAME,attributeID);

	Method method = getMethod(this->getMethodList(attributeID),optID);
	if (method){
		return method(message);
	}
	return HMC_Uknow_Equipment_Operation;
}

CommonOperation::Method CommonOperation::getMethod(vector <OptMethod *> *optMethodList,const int optID)
{
	vector <OptMethod *>::iterator it = this->find(optMethodList,optID);
	if (it != (*optMethodList).end()){
		return (*it)->method;
	}

	Debug("Not Found the method!\n");
	return NULL;
}

vector <CommonOperation::OptMethod *>::iterator CommonOperation::find(vector <OptMethod *> *optMethodList,const int optID)
{
	if ((optMethodList == NULL) ||(*optMethodList).size() == 0){
		Debug("The optMethodList is NULL!\n");
		return (*optMethodList).end();
	}
	vector <OptMethod *>::iterator it = (*optMethodList).begin();
	for (;it != (*optMethodList).end();it++){
		if (optID == (*it)->optID){
			return it;
		}
	}
	return ((*optMethodList).end());
}

vector <CommonOperation::OptMethod *> *CommonOperation::getMethodList(const string attributeID)
{
	vector <AttributeMethod *>::iterator it = this->find(attributeID);
	if (it != this->_attributeMethodList.end()){
		return &((*it)->methodList);
	}

	return NULL;
}

vector <CommonOperation::AttributeMethod *>::iterator CommonOperation::find(const string attributeID)
{
	if (this->_attributeMethodList.size() == 0){
		Debug("Need to add methods to the attributeMethodList!\n");
		return this->_attributeMethodList.end();
	}

	vector <AttributeMethod *>::iterator it = this->_attributeMethodList.begin();
	for (;it != this->_attributeMethodList.end();it++){
		if (attributeID == (*it)->attributeID){
			return it;
		}
	}

	Debug(string("Not found " + attributeID + "!\n").c_str());

	return this->_attributeMethodList.end();
}

bool CommonOperation::remove(const string attributeID)
{
	vector <AttributeMethod *>::iterator it = this->find(attributeID);
	if (it != this->_attributeMethodList.end()){
		vector <OptMethod *> mList = (*it)->methodList;
		for (unsigned int i = 0;i < mList.size();i++){
			this->remove(it,mList[i]->optID); 
		}
		delete (*it);
		this->_attributeMethodList.erase(it);
		return true;
	}

	return false;
}

bool CommonOperation::remove(const string attributeID,const int optID)
{
	vector <AttributeMethod *>::iterator it = this->find(attributeID);
	return this->remove(it,optID);
}

bool CommonOperation::remove(vector <AttributeMethod *>::iterator it,const int optID)
{
	if (it != this->_attributeMethodList.end()){
		vector <OptMethod *>::iterator mIt = this->find(&((*it)->methodList),optID);
		if (mIt != (*it)->methodList.end()){
			delete(*mIt);
			(*it)->methodList.erase(mIt);
			return true;
		}
	}
	return false;

}

